合成/聚合复用原则CARP
尽量使用合成/聚合,尽量不要使用类继承
- 聚合Aggregation 表示一种弱的’拥有’关系,体现A对象可以包含B对象,但B对象不是A对象的一部分
- 合成Composition 表示一种强的’拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样
比如,大雁和翅膀属于合成,大雁和雁群属于聚合
这个原则的好处是,优先使用对象的合成/聚合将有助于你保持每个类被封禁,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。
比如,A,B,C三种操作系统,X,Y,Z三种软件。每个系统都有这三种软件时,会发现一共有9种情况。
按照继承,有两种情况:
- 设计OS父类,ABC继承OS,ABC下分别有一个XYZ
- 设计Software父类,XYZ继承Software,XYZ下各有ABC三种版本
这时候,增加一种OS或者Software,再或者增加父类的方法,带来的影响就很大,导致最后规模越来越大。
定义
桥接模式将抽象部分与它实现的部分分离,使它们都可以独立地变化。
“将抽象部分与它的实现部分分离”指的是,前面的OS和Software有两种实现方式,现在就是要把这些实现分离开,独立出来,让它们各自变化。
UML
示例代码
// 软件类统一实现ISoftware接口
interface ISoftware {
public void run();
}
public class Software_X implements ISoftware {
@Override
public void run() {
System.out.println("Run software A");
}
}
public class Software_Y implements ISoftware {
@Override
public void run() {
System.out.println("Run software Y");
}
}
// OS类统一继承IOS 因为软件和OS属于聚合关系,OS持有一个software的引用
abstract class IOS {
protected ISoftware software;
public void setSoftware(ISoftware sw) {
this.software = sw;
}
public abstract void run();
}
public class OS_A extends IOS {
@Override
public void run() {
System.out.println("OSA");
software.run();
}
}
public class OS_B extends IOS {
@Override
public void run() {
System.out.println("OSB");
software.run();
}
}
//客户代码
public class main {
public static void main(String[] args) {
IOS os = new OS_A();
os.setSoftware(new Software_X());
os.run();
os.setSoftware(new Software_Y());
os.run();
os = new OS_B();
os.setSoftware(new Software_X());
os.run();
os.setSoftware(new Software_Y());
os.run();
}
}
//输出
OSA
Run software A
OSA
Run software Y
OSB
Run software A
OSB
Run software Y